package org.demo;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;

import org.boxlayout.gui.type.ColorEnum;

public class DemoFrame  extends Frame {

    Integer viewPortWidth = 0;
    Integer viewPortHeight = 0;

    GLCanvas canvas;
    GLU glu = new GLU();


    public DemoFrame() {
	super();



	//Threading.disableSingleThreading();        
	GLCapabilities caps = new GLCapabilities();
	caps.setDoubleBuffered( true );
	caps.setHardwareAccelerated( true );

	canvas = new GLCanvas(caps,null,GLContext.getCurrent(),null);
	//canvas.setBackground(Color.RED);
	canvas.addGLEventListener(new GLEventListener(){

	    public void init(GLAutoDrawable drawable) {
		//System.out.println("init");
		GL gl = drawable.getGL();
		//gl.glEnable(GL.GL_CULL_FACE);
		//gl.glEnable(GL.GL_DEPTH_TEST);
		//gl.glEnable(GL.GL_NORMALIZE);
		//gl.glShadeModel (GL.GL_SMOOTH);

		//gl.glBlendFunc(GL.GL_SRC_ALPHA_SATURATE, GL.GL_ONE);
		gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
		
		gl.glEnable(GL.GL_BLEND);
		//gl.glHint (GL.GL_LINE_SMOOTH_HINT, GL.GL_DONT_CARE);
		
		
		//gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_SRC_ALPHA);
		//gl.glBlendFunc(GL.GL_ONE, GL.GL_ZERO);
		//gl.glBlendFunc(GL.GL_SRC_ALPHA_SATURATE, GL.GL_ONE);
		//gl.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_DONT_CARE);
		//gl.glHint(GL.GL_LINE_SMOOTH_HINT,GL.GL_NICEST);



		//gl.setSwapInterval(0); 
		gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
		//gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
	    }
	    
	    public void drawCurveMano(GL gl, Float x1, Float y1, Float x2, Float y2, Float x3, Float y3, Float x4, Float y4 ,Boolean filled, ColorEnum color, Float alpha){
		/*gl.glCullFace( GL.GL_BACK );
		   // enable culling
		gl.glEnable( GL.GL_CULL_FACE );
	  
		
		gl.glClearColor( 1.0f, 1.0f, 1.0f, 0.0f );

		   // enable polygon antialiasing
		   gl.glBlendFunc( GL.GL_SRC_ALPHA_SATURATE, GL.GL_ONE );
		   gl.glEnable( GL.GL_BLEND );
		   gl.glEnable( GL.GL_POLYGON_SMOOTH );
		   gl.glDisable( GL.GL_DEPTH_TEST );
	*/
		
		
		Float lastX = x1;
		Float lastY = y1;
		Double x;
		Double y;
		Double _1mt,tp3,tp2,_1mtp2,_1mtp3;

		/*
		lastX = x1;
		lastY = y1;
		ColorEnum.WHITE.apply(gl);
		gl.glPointSize(1f);
		//gl.glEnable(GL.GL_POINT_SMOOTH);
		gl.glBegin(GL.GL_POINTS);
		//for(Double t = 1.0d;t>=0.0d;t-=0.1d){
		for(Double t = 0d;t<=1.1d;t+=0.1d){
		    _1mt = 1-t;
		    tp3 = Math.pow(t, 3);
		    tp2 = Math.pow(t, 2);
		    _1mtp2 = Math.pow(_1mt, 2);
		    _1mtp3 = _1mtp2*(_1mt);
		    //P1*t^3 + P2*3*t^2*(1-t) + P3*3*t*(1-t)^2 + P4*(1-t)^3 = Pnew
		    x = x1*tp3 + x2*3*tp2*_1mt + x3*3*t*_1mtp2 + x4*_1mtp3;
		    y = y1*tp3 + y2*3*tp2*_1mt + y3*3*t*_1mtp2 + y4*_1mtp3;
		    gl.glVertex3f(lastX,lastY, 0f);
		    //gl.glVertex3f(x.floatValue(),y.floatValue(), 0f);
		    lastX = x.floatValue();
		    lastY = y.floatValue();
		}
		gl.glEnd();
		*/
		lastX = x1;
		lastY = y1;
		//gl.glHint(GL.GL_POLYGON_SMOOTH, GL.GL_NICEST); 
		//gl.glEnable(GL.GL_POLYGON_SMOOTH);
		//gl.glBegin(GL.GL_POLYGON);
		gl.glEnable(GL.GL_LINE_SMOOTH);
		gl.glLineWidth(1f);
		gl.glBegin(GL.GL_LINE_STRIP_ADJACENCY_EXT);
		ColorEnum.BLACK.apply(gl);
		System.out.println("begin");
		//for(Double t = 1.0d;t>=0.0d;t-=0.1d){
		for(Double t = 0d;t<=1.2d;t+=0.1d){
		    System.out.println(lastX+" "+lastY);
		    _1mt = 1-t;
		    tp3 = Math.pow(t, 3);
		    tp2 = Math.pow(t, 2);
		    _1mtp2 = Math.pow(_1mt, 2);
		    _1mtp3 = _1mtp2*(_1mt);
		    //P1*t^3 + P2*3*t^2*(1-t) + P3*3*t*(1-t)^2 + P4*(1-t)^3 = Pnew
		    x = x1*tp3 + x2*3*tp2*_1mt + x3*3*t*_1mtp2 + x4*_1mtp3;
		    y = y1*tp3 + y2*3*tp2*_1mt + y3*3*t*_1mtp2 + y4*_1mtp3;
		    gl.glVertex3f(lastX,lastY, 0f);
		    gl.glVertex3f(x.floatValue(),y.floatValue(), 0f);
		    lastX = x.floatValue();
		    lastY = y.floatValue();
		}
		System.out.println("end");
		/*
		gl.glVertex3f(x1,y1, 0f);
		gl.glVertex3f(x2,y2, 0f);
		gl.glVertex3f(x3,y3, 0f);
		gl.glVertex3f(x4,y4, 0f);
		*/
		gl.glEnd();
		
	    }
	    
	    private void drawCurve(GL gl) {
		Float r = 1f;
		Float x = 0f;
		Float y = 0f;
		
		drawCurveMano(gl, 
			x+0f, y+0f, 
			x+0f, y+1f, 
			x+0f, y+1f, 
			x+2f, y+2f,
			true,

			ColorEnum.WHITE,1f);
		
		
		
	    }

	    public void display(GLAutoDrawable drawable) {
		//System.out.println("display");
		GL gl = drawable.getGL();

		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glLoadIdentity();

		//camera.display(glu);
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

		drawCurve(gl);
		//drawLine(gl);
		//drawPoly(gl);

		gl.glFlush();



	    }

	    private void drawPoly(GL gl) {
		//GL_POINT_SMOOTH_HINT, GL_LINE_SMOOTH_HINT, GL_POLYGON_SMOOTH_HINT
		//gl.glEnable(GL.GL_POLYGON_SMOOTH);
		//gl.glEnable(GL.GL_LINE_SMOOTH_HINT);
		float yDirection = -1f;
		float height = 1f;
		float width = 1f;
		float r = 0f;
		ColorEnum.WHITE.apply(gl);
		gl.glRotatef(40f, 0f, 0f, 1f);
		gl.glBegin(GL.GL_POLYGON);
		//gl.glLineWidth(2f);
		//gl.glBegin(GL.GL_LINE_STRIP);
		//if(color!=null)color.applyWithAlpha(gl, alpha);
		gl.glVertex3f(0f,yDirection*(height-r), 0f);
		gl.glVertex3f(r,yDirection*height, 0f);        
		gl.glVertex3f(width-r,yDirection*height, 0f);
		gl.glVertex3f(width,yDirection*(height-r), 0f);
		//if(color2!=null)color2.applyWithAlpha(gl, alpha);  
		gl.glVertex3f(width,yDirection*r, 0f);
		gl.glVertex3f(width-r,0f, 0f);
		gl.glVertex3f(r,0f, 0f);
		gl.glVertex3f(0f,yDirection*r, 0f);
		gl.glEnd();
		
		gl.glBegin(GL.GL_LINE_STRIP);
		gl.glLineWidth(2f);
		//gl.glBegin(GL.GL_LINE_STRIP);
		//if(color!=null)color.applyWithAlpha(gl, alpha);
		gl.glVertex3f(0f,yDirection*(height-r), 0f);
		gl.glVertex3f(r,yDirection*height, 0f);        
		gl.glVertex3f(width-r,yDirection*height, 0f);
		gl.glVertex3f(width,yDirection*(height-r), 0f);
		//if(color2!=null)color2.applyWithAlpha(gl, alpha);  
		gl.glVertex3f(width,yDirection*r, 0f);
		gl.glVertex3f(width-r,0f, 0f);
		gl.glVertex3f(r,0f, 0f);
		gl.glVertex3f(0f,yDirection*r, 0f);
		gl.glEnd();
	    }

	    private void drawLine(GL gl) {
		gl.glLineWidth(4f);
		gl.glEnable(GL.GL_LINE_SMOOTH);
		gl.glBegin(GL.GL_LINE_STRIP);
		//if(color!=null)color.applyWithAlpha(gl, alpha);
		gl.glVertex3f(0f,0f, 0f);
		gl.glVertex3f(1f,2f, 0f);        

		gl.glEnd();
	    }

	   

	    public void handleView(GL gl, GLU glu) {
		double aspectRatio = (double)viewPortWidth / (double)viewPortHeight;
		//glu.gluPerspective(55.0, aspectRatio, 0.01, 50.0);
		glu.gluOrtho2D(-4.0d, 4.0d, -4.0d, 4.0d);
		//gl.glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f);   
	    }

	    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
		viewPortWidth = width;
		viewPortHeight = height;

		GL gl = drawable.getGL();
		gl.glViewport(0, 0, viewPortWidth, viewPortHeight); //set viewport
		gl.glMatrixMode(GL.GL_PROJECTION); //go to projection mode
		gl.glLoadIdentity(); // reset it        

		handleView(gl,glu); // change the view 

		gl.glMatrixMode(GL.GL_MODELVIEW); //go to default mode
		gl.glLoadIdentity(); // reset it
	    }

	    @Override
	    public void displayChanged(GLAutoDrawable arg0,
		    boolean arg1, boolean arg2) {
		// TODO Auto-generated method stub

	    }
	});
	//ViewHandler,

	add(canvas);

	setSize(900, 900);
	//final Animator animator = new FPSAnimator(canvas,120);
	//animator.setRunAsFastAsPossible(false);
	//animator.setPrintExceptions(true);
	addWindowListener(new WindowAdapter() {

	    public void windowClosing(WindowEvent e) {
		new Thread(new Runnable() {

		    public void run() {
			//animator.stop();
			System.exit(0);
		    }
		}).start();
	    }
	});
	setVisible(true);

	addWindowListener( new WindowAdapter() {
	    public void windowActivated( WindowEvent e ) {
		canvas.requestFocusInWindow(); } } );

	//requestFocus();
	//canvas.requestFocusInWindow();
	//animator.start();
	setFocusable(true);
	setFocusableWindowState(true);
    }
    
    
    

    public static void main(String[] args) {
	new DemoFrame();
    }

}
